/*
 * Copyright (C) 2012 Santiago Valdarrama
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package com.yuanmei.stockeyes.layouts;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
//import android.widget.TextView;

import android.widget.TextView;

import com.yuanmei.stockeyes.R;
import com.yuanmei.stockeyes.activities.StockAnalysisActivity;
import com.yuanmei.stockeyes.artifacts.Extensions;
import com.yuanmei.stockeyes.artifacts.GlobalSettings;
import com.yuanmei.stockeyes.artifacts.StockOverviewManager;
import com.yuanmei.stockeyes.model.Stock;
import com.yuanmei.stockeyes.data.DataProvider;
import com.yuanmei.stockeyes.data.HistoryQuotesDataBase.HistoryRecord;

import cn.limc.androidcharts.entity.DateValueEntity;
import cn.limc.androidcharts.entity.IStickEntity;
import cn.limc.androidcharts.entity.LineEntity;
import cn.limc.androidcharts.entity.ListChartData;
import cn.limc.androidcharts.entity.OHLCEntity;
import cn.limc.androidcharts.view.GridChart;
import cn.limc.androidcharts.view.MACandleStickChart;
//import cn.limc.androidcharts.view.MAColoredStickChart;
import financedata.historicalquotes.Interval;

 
public class StockOverviewLayout extends LinearLayout implements DataProvider.AsyncDownloadCallback{

    private final static float STOCK_PRICE_ANIMATION_STEPS = 10;
    private final static int   KLINE_SHOW_NUM = 45;

    private static final String LOG_TAG = "StockOverviewLayout";

    //private TextView lastTradeDateTextView;
    private StockPriceAnimationAsyncTask stockPriceAnimationAsyncTask;
    private Stock     mStock = null;
    private ViewGroup mStockOverviewContentLayout;
    private LinearLayout mLnTopTabHead;
    
    private LinearLayout mKlineChart;
    private MACandleStickChart  mOhlcChart;
    //private MAColoredStickChart mVolChart;
    List<IStickEntity> mCandleStickList = new ArrayList<IStickEntity>();
    List<LineEntity<DateValueEntity>> mSMALines = new ArrayList<LineEntity<DateValueEntity>>();
    
    private ImageView mDownloadView;
    private Animation mDownloadAnim;
    private Context   mContext;
    private DisplayMetrics mDisplayMetrics;
    
    
    public static enum TabName {
        CONTENT_TAB,
        DAY_KLINE_TAB,
        WEEK_KLINE_TAB,
        MONTH_KLINE_TAB
    }
    
    private TabName  mCurrentTabName;
    private View     mCurrentTabHeadVw = null;
    
    private StockOverviewManager stockOverviewManager;
    
    
    private class DoubleClickListener implements View.OnTouchListener{

        private int  down_cnt;
        private long first_tm; 

        public void resetState() {
            down_cnt = 0;
            first_tm = 0;
        }
        
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(MotionEvent.ACTION_DOWN == event.getAction()){
                 down_cnt++;
                 if(down_cnt == 1) {
                     first_tm = System.currentTimeMillis();
                 } else if (down_cnt == 2) {
                     if(System.currentTimeMillis() < (first_tm + 2000)) {
                         //showLargeBmp();
                         Intent intent = new Intent();
                         intent.putExtra(StockAnalysisActivity.ANALYSIS_CODE, mStock.getCode());
                         if (mCurrentTabName == TabName.MONTH_KLINE_TAB) {
                             intent.putExtra(StockAnalysisActivity.ANALYSIS_INTERVAL, Interval.MONTHLY.getTag());
                         } else if (mCurrentTabName == TabName.WEEK_KLINE_TAB) {
                             intent.putExtra(StockAnalysisActivity.ANALYSIS_INTERVAL, Interval.WEEKLY.getTag());
                         } else {
                             intent.putExtra(StockAnalysisActivity.ANALYSIS_INTERVAL, Interval.DAILY.getTag());
                         }

                         intent.setClassName(mContext, StockAnalysisActivity.class.getName());
                         mContext.startActivity(intent);
                     }
                     down_cnt = 0;
                     first_tm = 0;
                 } else {
                     down_cnt = 0;
                     first_tm = 0;
                 }
             }
             return false;
         }
     
    }
    
    DoubleClickListener mDclickListener;

    public StockOverviewLayout(final Context context) {
        super(context);
        mContext = context;
        this.mStock = null;

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.stock_overview, this);
        
        WindowManager winManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        mDisplayMetrics = new DisplayMetrics();
        winManager.getDefaultDisplay().getMetrics(mDisplayMetrics);

        Stock.initKlineBaseDir(context.getFilesDir().getAbsolutePath());

        this.mStockOverviewContentLayout = (ViewGroup) findViewById(R.id.stockOverviewContentLayout);
        this.mLnTopTabHead = (LinearLayout) findViewById(R.id.TopTabHead);
        
        this.mKlineChart = (LinearLayout) findViewById(R.id.KlineChart);
        this.mOhlcChart  = (MACandleStickChart) findViewById(R.id.OhlcChart);
        this.mOhlcChart.disableTouchProcess();
        configOhlcChart();
        
        //this.mVolChart   = (MAColoredStickChart) findViewById(R.id.VolChart);        

        this.mDownloadAnim = AnimationUtils.loadAnimation(context, R.anim.download_rotate);
        this.mDownloadView = (ImageView) findViewById(R.id.DownloadImage);
        
        findViewById(R.id.fiveBid).setOnClickListener(
            new OnClickListener() {
                @Override
                public void onClick(View v) {
                    setCurrentTab(v, TabName.CONTENT_TAB);
                    refreshCurrnetTab();
                }
            }
        );
        
        findViewById(R.id.dayKLine).setOnClickListener(
            new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onKchartTabClick(v, TabName.DAY_KLINE_TAB);
                }
            }
        );

        findViewById(R.id.weekKLine).setOnClickListener(
           new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onKchartTabClick(v, TabName.WEEK_KLINE_TAB);
                }
           }
        );
        
        findViewById(R.id.monthKLine).setOnClickListener(
            new OnClickListener() {
                @Override
                public void onClick(View v) {
                    onKchartTabClick(v, TabName.MONTH_KLINE_TAB);
                }
            }
        );
        
        mDclickListener = new DoubleClickListener();
        this.setOnTouchListener(mDclickListener);

        this.stockOverviewManager = new StockOverviewManager(this.mStockOverviewContentLayout);
        //this.lastTradeDateTextView = (TextView) findViewById(R.id.lastTradeDateTextView);
    }

    public void setStock(Stock stock) {
        mStock = stock;

        //Extensions.applyPattern(getResources(), this.mStockOverviewContentLayout, stock);
        
        this.stockOverviewManager.setStock(mStock);
        if (mCurrentTabHeadVw == null) {
            setCurrentTab(findViewById(R.id.fiveBid), TabName.CONTENT_TAB);
        }
        refreshCurrnetTab();
        /*
        if (this.lastTradeDateTextView != null) {
            this.lastTradeDateTextView.setText(this.stock.getLastTradeDate());
        }
        */
    
    }

    public Stock getStock() {
        return mStock;
    }
        
    private void setCurrentTab(View v, TabName tab){
        this.mCurrentTabName    = tab;
        this.mCurrentTabHeadVw  = v;
    }

    private void onKchartTabClick(View v, TabName tabName){      
        setCurrentTab(v, tabName);
        refreshCurrnetTab();
    }

    @Override
    public void onDownloadOver() {
        refreshCurrnetTab();
    }

    private List<HistoryRecord>  getHisData(TabName tab, boolean isReValid){
        List<HistoryRecord> hisRecs = null;
        if (TabName.DAY_KLINE_TAB == tab){
            hisRecs = DataProvider.getLastNumHisRecords(mContext, 
                mStock.getCode(), Interval.DAILY, KLINE_SHOW_NUM, isReValid, this);
        } else if (TabName.WEEK_KLINE_TAB == tab) {
            hisRecs = DataProvider.getLastNumHisRecords(mContext, 
                mStock.getCode(), Interval.WEEKLY, KLINE_SHOW_NUM, isReValid, this);
        } else if (TabName.MONTH_KLINE_TAB == tab) {
            hisRecs = DataProvider.getLastNumHisRecords(mContext, 
                mStock.getCode(), Interval.MONTHLY, KLINE_SHOW_NUM, isReValid, this);
        }

        return hisRecs;
    }
    
    private void configOhlcChart() {
        
        mOhlcChart.setAxisXColor(Color.LTGRAY);
        mOhlcChart.setAxisYColor(Color.LTGRAY);
        mOhlcChart.setLatitudeColor(Color.GRAY);
        mOhlcChart.setLongitudeColor(Color.GRAY);
        mOhlcChart.setBorderColor(Color.TRANSPARENT);
        mOhlcChart.setLongitudeFontColor(Color.WHITE);
        mOhlcChart.setLatitudeFontColor(Color.WHITE);
        
        // 最大纬线数
        mOhlcChart.setLatitudeNum(5);
        // 最大经线数
        mOhlcChart.setLongitudeNum(3);
        
        mOhlcChart.setDisplayLongitudeTitle(true);
        mOhlcChart.setDisplayLatitudeTitle(true);
        mOhlcChart.setDisplayLatitude(true);
        mOhlcChart.setDisplayLongitude(true);
        mOhlcChart.setBackgroundColor(Color.BLACK);
        
        mOhlcChart.setDataQuadrantPaddingTop(5);
        mOhlcChart.setDataQuadrantPaddingBottom(5);
        mOhlcChart.setDataQuadrantPaddingLeft(5);
        mOhlcChart.setDataQuadrantPaddingRight(5);
        mOhlcChart.setAxisYTitleQuadrantWidth(50);
        mOhlcChart.setAxisXTitleQuadrantHeight(20);
        mOhlcChart.setAxisXPosition(GridChart.AXIS_X_POSITION_BOTTOM);
        mOhlcChart.setAxisYPosition(GridChart.AXIS_Y_POSITION_RIGHT);

    }


    private LineEntity<DateValueEntity> calcSMALine(List<IStickEntity> ohlcLists,
            int period, int color) {

        if (period < 2) {
            return null;
        }

        List<DateValueEntity> SMAValues = new ArrayList<DateValueEntity>();
        float sum = 0;
        float avg = 0;
        for (int i = 0; i < ohlcLists.size() ; i++) {
            float close = (float) ((OHLCEntity) ohlcLists.get(i)).getClose();
            if (i < period) {
                sum = sum + close;
                avg = sum / (i + 1f);
            } else {
                sum = sum + close - 
                        (float) ((OHLCEntity) ohlcLists.get(i - period)).getClose();;
                avg = sum / period;
            }
            SMAValues.add(new DateValueEntity((float)avg, ohlcLists.get(i).getDate()));
        }

        LineEntity<DateValueEntity> smaLine = new LineEntity<DateValueEntity>();
        smaLine.setTitle("MA" + period);
        smaLine.setLineColor(color);

        smaLine.setLineData(SMAValues);
        return smaLine;

    }
    
    private void redrawKLineChart(List<HistoryRecord> hisRecs) {

        mCandleStickList.clear();

        double maxValue = Double.MIN_VALUE;
        double minValue = Double.MAX_VALUE;
        
        float[] inCloses = new float[hisRecs.size()];
        int[]   inDates  = new int[hisRecs.size()];
        for (int i = hisRecs.size() - 1; i >= 0; i--) {
            
            HistoryRecord rec = hisRecs.get(i);
            mCandleStickList.add(new OHLCEntity(rec.mOpen, rec.mHigh,
                    rec.mLow, rec.mClose, (int) rec.mDate));
            if (rec.mHigh > maxValue) {
                maxValue = rec.mHigh;
            }
            if (rec.mLow < minValue) {
                minValue = rec.mLow;
            }
            inCloses[i] = rec.mClose;
            inDates[i]  = (int) rec.mDate;
        }

        // 最大显示足数
        int stickNum = mCandleStickList.size();
        mOhlcChart.setDisplayNumber(stickNum);

        // 最大价格
        mOhlcChart.setMaxValue(maxValue);
        // 最小价格
        mOhlcChart.setMinValue(minValue);
        // 为chart2增加均线
        mOhlcChart.setStickData( new ListChartData<IStickEntity>(mCandleStickList));
        // mOhlcChart.setStickData(mCandleStickList);
        
        mSMALines.clear();
        mSMALines.add(calcSMALine(mCandleStickList, 5, Color.WHITE));
        mSMALines.add(calcSMALine(mCandleStickList, 10, Color.RED));

        mOhlcChart.setLinesData(mSMALines);
        mOhlcChart.invalidate();
    }

    public void refreshCurrnetTab() {
        
        mDclickListener.resetState();
        //refresh head
        int size = mLnTopTabHead.getChildCount();
        for (int i=0; i < size; i++){
            TextView childView = (TextView) mLnTopTabHead.getChildAt(i);
            if (mCurrentTabHeadVw == childView) {
                childView.setBackgroundResource(R.drawable.pattern_background_blue);
            } else {
                childView.setBackgroundResource(R.drawable.horizontal_top_shadow);
            }
        }
        
        //refresh tab contains
        if (this.mCurrentTabName == TabName.CONTENT_TAB) {
            //show content
            mKlineChart.clearAnimation();
            mDownloadView.clearAnimation();
            mKlineChart.setVisibility(View.GONE);
            mStockOverviewContentLayout.setVisibility(View.VISIBLE);
            return;
        }

        //show k-line  
//        if (!Stock.isKlineDirOK()) {
//            Log.e(LOG_TAG, "isKlineDirOK is not be inited");
//            return;
//        }
        
        boolean isNeedCheckUpdate;
        if (!Extensions.areWeOnline(mContext)) {
            isNeedCheckUpdate = false;
        } else { 
            if (Extensions.areWeUsingWiFi(mContext)) {
                isNeedCheckUpdate = true;
            } else {
                if (GlobalSettings.sbIsOnlyWifiDownloadChart) {
                    isNeedCheckUpdate = false;
                } else {
                    isNeedCheckUpdate = true;
                }
            }
        }

        List<HistoryRecord> hisRecs = getHisData(mCurrentTabName, isNeedCheckUpdate);
        if (null == hisRecs) {
            if (isNeedCheckUpdate) { 
                mDownloadView.startAnimation(mDownloadAnim);
                mDownloadView.setImageResource(R.drawable.loading);
                mDownloadView.setScaleType(ImageView.ScaleType.CENTER);
                mDownloadView.setVisibility(View.VISIBLE);
                
                mStockOverviewContentLayout.setVisibility(View.GONE);
                mKlineChart.setVisibility(View.GONE);
            } else {
                String toast_message = mContext.getResources().getString(R.string.net_offline_message);
                if (Extensions.areWeOnline(mContext) && (GlobalSettings.sbIsOnlyWifiDownloadChart)) {
                    toast_message = mContext.getResources().getString(R.string.wifi_offline_message);
                }
                mDownloadView.setImageBitmap(null);
                Toast toast = Toast.makeText(mContext, toast_message, Toast.LENGTH_LONG);
                toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
                toast.setMargin(0f, 0f);
                toast.show();
            }
        } else {
            mDownloadView.clearAnimation();
            mKlineChart.clearAnimation(); 
            redrawKLineChart(hisRecs);
            mKlineChart.invalidate();
  
            String toast_message = mContext.getResources().getString(R.string.toast_kchart_dclick_note);

//            if( DataProvider.isHistoricalQuotesNeedUpdate(mContext)){
//                toast_message = mContext.getResources().getString(R.string.toast_needupdate_dclick_note);
//            }
            Toast toast = Toast.makeText(mContext, toast_message, Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
            toast.setMargin(0f, 0f);
            toast.show();
            
            mKlineChart.setVisibility(View.VISIBLE);
            mStockOverviewContentLayout.setVisibility(View.GONE);
            mDownloadView.setVisibility(View.GONE);
        }
        return;
    }

    public void animateContent() {
        if (mStock != null) {
            if (this.stockPriceAnimationAsyncTask != null) {
                this.stockPriceAnimationAsyncTask.cancel(true);
                this.stockPriceAnimationAsyncTask = null;
            }
    
            if (mStock.getPrice() != null && mStock.getOpen() != null) {
                this.stockOverviewManager.setPrice(mStock.getStringOpen());
    
                float increment = (mStock.getPrice() - mStock.getOpen()) / STOCK_PRICE_ANIMATION_STEPS;
    
                this.stockPriceAnimationAsyncTask = new StockPriceAnimationAsyncTask();
                this.stockPriceAnimationAsyncTask.execute(mStock.getPrice(), mStock.getOpen(), increment);
            }
        }
    }

    private class StockPriceAnimationAsyncTask extends AsyncTask<Float, Float, Void> {
    
        private float price;
    
        @Override
        protected Void doInBackground(Float... params) {
            this.price = params[0];
            float open = params[1];
            float increment = params[2];
    
            for (int i = 0; i < STOCK_PRICE_ANIMATION_STEPS; i++) {
                if (!this.isCancelled()) {
                    try {
                        open += increment;
                        publishProgress(open);
                        Thread.sleep(40);
                    }
                    catch (InterruptedException e) {
                        return null;
                    }
                }
            }
    
            return null;
        }
    
        @Override
        protected void onProgressUpdate(Float... values) {
            float value = values[0];
            StockOverviewLayout.this.stockOverviewManager.setPrice(Extensions.format(value));
        }
    
        @Override
        protected void onPostExecute(Void result) {
            StockOverviewLayout.this.stockOverviewManager.setPrice(Extensions.format(this.price));
        }
    }
}
